package com.qingyun.shop.service.impl;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.collection.CollectionUtil;
import cn.hutool.core.io.FileUtil;
import cn.hutool.core.io.IoUtil;
import cn.hutool.core.util.IdUtil;
import cn.hutool.core.util.ObjectUtil;
import cn.hutool.http.HttpUtil;
import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.qingyun.common.config.QingYunConfig;
import com.qingyun.common.constant.Constants;
import com.qingyun.common.exception.ServiceException;
import com.qingyun.common.utils.BaiduMp3Util;
import com.qingyun.common.utils.DateUtils;
import com.qingyun.common.utils.PageUtils;
import com.qingyun.common.core.page.PagePlus;
import com.qingyun.common.core.page.TableDataInfo;
import com.qingyun.common.utils.file.FileUploadUtils;
import com.qingyun.security.utils.SecurityUtils;
import com.qingyun.shop.domain.TiktokShop;
import com.qingyun.shop.domain.TiktokTagToVoice;
import com.qingyun.shop.domain.TiktokVoice;
import com.qingyun.shop.domain.bo.resource.TiktokVoiceBo;
import com.qingyun.shop.domain.vo.TiktokVoiceVo;
import com.qingyun.shop.mapper.TiktokTagToVoiceMapper;
import com.qingyun.shop.mapper.TiktokVoiceMapper;
import com.qingyun.shop.service.ITiktokShopService;
import com.qingyun.shop.service.ITiktokVoiceService;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import com.qingyun.common.core.mybatisplus.core.ServicePlusImpl;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;
import java.io.BufferedInputStream;
import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.net.HttpURLConnection;
import java.net.URL;
import java.util.*;

/**
 * 合成语音Service业务层处理
 *
 * @author qingyun
 * @date 2021-10-21
 */
@Service
@Slf4j
public class TiktokVoiceServiceImpl extends ServicePlusImpl<TiktokVoiceMapper, TiktokVoice, TiktokVoiceVo> implements ITiktokVoiceService {

	@Autowired
	private ITiktokShopService shopService;

	@Resource
	private TiktokTagToVoiceMapper tagToVoiceMapper;

	@Autowired
	private QingYunConfig qingYunConfig;

	@Autowired
	private BaiduMp3Util baiduMp3Util;

    @Override
    public TiktokVoiceVo queryById(Long id){
        return getVoById(id);
    }

    @Override
    public TableDataInfo<TiktokVoiceVo> queryPageList(TiktokVoiceBo bo) {
    	if(!SecurityUtils.isManager()){
    		bo.setShopId(SecurityUtils.getShop().getId());
		}
        PagePlus<TiktokVoice, TiktokVoiceVo> result = pageVo(PageUtils.buildPagePlus(), buildQueryWrapper(bo));
    	result.getRecordsVo().forEach((voice)->{
    		voice.setTagList(tagToVoiceMapper.selectVoiceTagStr(voice.getId()));
		});
        return PageUtils.buildDataInfo(result);
    }

    @Override
    public List<TiktokVoiceVo> queryList(TiktokVoiceBo bo) {
        return listVo(buildQueryWrapper(bo));
    }

    private LambdaQueryWrapper<TiktokVoice> buildQueryWrapper(TiktokVoiceBo bo) {
        LambdaQueryWrapper<TiktokVoice> lqw = Wrappers.lambdaQuery();
        lqw.eq(bo.getShopId() != null, TiktokVoice::getShopId, bo.getShopId());
        lqw.like(bo.getShopName()!=null,TiktokVoice::getShopName,bo.getShopName());
        lqw.eq(StringUtils.isNotBlank(bo.getTitle()), TiktokVoice::getTitle, bo.getTitle());
        return lqw;
    }

    @Override
	@Transactional(rollbackFor = Exception.class)
    public Boolean insertByBo(TiktokVoiceBo bo) {
        TiktokVoice add = BeanUtil.toBean(bo, TiktokVoice.class);
        if(!SecurityUtils.isManager()){
        	add.setShopId(SecurityUtils.getShop().getId());
        	add.setShopName(SecurityUtils.getShop().getName());
		}else{
			if (bo.getShopId()==null) {
				throw new ServiceException("管理员添加shopId不能为空");
			}
		}
		TiktokShop shop = shopService.lambdaQuery().select(TiktokShop::getName).eq(TiktokShop::getId,add.getShopId()).one();
        if(ObjectUtil.isNull(shop)){
        	throw new ServiceException("商户不存在");
		}

		add.setShopName(shop.getName());
		String uuid = IdUtil.fastUUID();
		String mp3OutPath = QingYunConfig.getProfile()+"/voice/"+ uuid+".mp3";
		String srtOutPath = QingYunConfig.getProfile()+"/voice/"+ uuid+"_txt.srt";
		//开始合成
//		String generate = baiduMp3Util.generate(bo.getContext(), outPath,bo.getPer());
//		if (generate!=null) {
//			String pathFileName =  Constants.RESOURCE_PREFIX+StringUtils.substringAfter(outPath,QingYunConfig.getProfile());
//			add.setVoice(qingYunConfig.getProjectUrl()+pathFileName);
//		}else{
//			log.info("语音合成失败");
//			return false;
//		}
		if (saveFile(bo.getContext(),bo.getPer(),mp3OutPath,srtOutPath)) {
			String pathMp3Name =  Constants.RESOURCE_PREFIX+StringUtils.substringAfter(mp3OutPath,QingYunConfig.getProfile());
			String pathSrtName =  Constants.RESOURCE_PREFIX+StringUtils.substringAfter(srtOutPath,QingYunConfig.getProfile());
			add.setVoice(qingYunConfig.getProjectUrl()+pathMp3Name);
			add.setSrt(qingYunConfig.getProjectUrl()+pathSrtName);
		}else{
		  log.info("语音合成失败");
    	  return false;
		}
		save(add);
		List<Long> tags = bo.getTags();
		if(CollectionUtil.isNotEmpty(tags)){
			List<TiktokTagToVoice> voiceTages = new ArrayList<>();
			tags.forEach((tagId)->{
				TiktokTagToVoice tiktokTagToVoice = new TiktokTagToVoice();
				tiktokTagToVoice.setTagId(tagId);
				tiktokTagToVoice.setVoiceId(add.getId());
				voiceTages.add(tiktokTagToVoice);
			});
			tagToVoiceMapper.insertAll(voiceTages);
		}
		return true;
    }

    @Override
	@Transactional(rollbackFor = Exception.class)
    public Boolean updateByBo(TiktokVoiceBo bo) {
        TiktokVoice update = BeanUtil.toBean(bo, TiktokVoice.class);
        //先删除后新增
		tagToVoiceMapper.delete(Wrappers.lambdaQuery(TiktokTagToVoice.class).eq(TiktokTagToVoice::getVoiceId, bo.getId()));
		List<TiktokTagToVoice> voiceTages = new ArrayList<>();
		List<Long> tags = bo.getTags();
		tags.forEach((tagId)->{
			TiktokTagToVoice tiktokTagToVoice = new TiktokTagToVoice();
			tiktokTagToVoice.setTagId(tagId);
			tiktokTagToVoice.setVoiceId(bo.getId());
			voiceTages.add(tiktokTagToVoice);
		});
		tagToVoiceMapper.insertAll(voiceTages);
		return updateById(update);
    }

    /**
     * 保存前的数据校验
     *
     * @param entity 实体类数据
     */
    private void validEntityBeforeSave(TiktokVoice entity){
        //TODO 做一些数据校验,如唯一约束
    }

    @Override
    public Boolean deleteWithValidByIds(Collection<Long> ids, Boolean isValid) {
        ids.forEach(id->{
			TiktokVoice voice = getById(id);
			tagToVoiceMapper.delete(Wrappers.lambdaQuery(TiktokTagToVoice.class).eq(TiktokTagToVoice::getVoiceId, voice.getId()));
			String localPath = QingYunConfig.getProfile() + StringUtils.substringAfter(voice.getVoice(),  Constants.RESOURCE_PREFIX);
			File file = new File(localPath);
			if (file.exists()) {
				file.delete();
			}
			String srtPath=localPath.substring(0,localPath.indexOf("."))+".txt.srt";
			File srtfile = new File(srtPath);
			if (srtfile.exists()) {
				srtfile.delete();
			}
		});
        return removeByIds(ids);
    }



    //此接口只允许测试 如需使用请联系作者
	private boolean saveFile(String text,String voice,String mp3OutPath,String srtOutPath) {
    	try {
			HashMap<String, Object> param = new HashMap<>();
			param.put("format", "mp3");
			param.put("text", text);
			param.put("voice", voice);
			param.put("speech_rate", "0");
			param.put("pitch_rate", "0");
			param.put("sample_rate", "24000");
			param.put("appid", "20211116h7QJOpn");
			param.put("token", "tQzThR8icp81hQjicRwKSaVdunUi8XvW");
			param.put("tone_pause_mill_sec", "120");
			String result = HttpUtil.post("http://openplat.muyanpeiyin.com/tts/v2", param);
			System.out.println(result);
			JSONObject jsonObject = JSONObject.parseObject(result);
			JSONObject data = jsonObject.getJSONObject("data");
			String audio = (String) data.get("audio");
			String srt = (String) data.get("srt");
			InputStream inputStreamAudio = new URL(audio).openStream();
			BufferedInputStream bufferedInputStreamAudio = new BufferedInputStream(inputStreamAudio);
			FileUtil.writeFromStream(bufferedInputStreamAudio, new File(mp3OutPath));
			inputStreamAudio.close();
			InputStream inputStreamSrt =new URL(srt).openStream();
			BufferedInputStream bufferedInputStreamSrt = new BufferedInputStream(inputStreamSrt);
			FileUtil.writeFromStream(bufferedInputStreamSrt,new File(srtOutPath));
			inputStreamSrt.close();
		}catch (Exception e){
    		e.printStackTrace();
    		return false;
		}
		return true;
	}

	/**
	 * 根据url下载文件流
	 * @param urlStr
	 * @return
	 */
	private InputStream getInputStreamFromUrl(String urlStr) {
		InputStream inputStream=null;
		try {
			//url解码
			URL url = new URL(java.net.URLDecoder.decode(urlStr, "UTF-8"));
			HttpURLConnection conn = (HttpURLConnection) url.openConnection();
			//设置超时间为3秒
			conn.setConnectTimeout(80 * 1000);
			//防止屏蔽程序抓取而返回403错误
			conn.setRequestProperty("User-Agent", "Mozilla/4.0 (compatible; MSIE 5.0; Windows NT; DigExt)");
			//得到输入流
			inputStream = conn.getInputStream();
		} catch (IOException e) {
			e.printStackTrace();
		}
		return inputStream;
	}

}
